package com.candoit.webapps.pricing.util.spreadsheet;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.candoit.webapps.pricing.model.Articulo;
import com.candoit.webapps.pricing.model.MateriaPrima;
import com.candoit.webapps.pricing.model.MateriaPrimaArticulo;
import com.candoit.webapps.pricing.model.Moneda;
import com.candoit.webapps.pricing.model.TipoLinea;
import com.candoit.webapps.pricing.model.TipoMateriaPrima;
import com.candoit.webapps.pricing.util.QueryUtil;

public class CommandMPForSpreadsheet {

	private Map<TipoMateriaPrima,Double> costosMateriasPrimasNoPapel;
	private Map<TipoMateriaPrima,Double> consumosMateriasPrimas;
	private Moneda moneda;
	private TipoLinea tipoProductivo;
	private static final Double proporcionScrap = 0.1;
	
	public CommandMPForSpreadsheet(TipoLinea tipoProductivo){
		costosMateriasPrimasNoPapel = null;
		consumosMateriasPrimas = null;
		moneda = QueryUtil.getInstance().getCotizacionMoneda();
		this.tipoProductivo = tipoProductivo;
	}
	
	public Map<MateriaPrima, CommandMPCostsDetails> listarValoresPorArticulo(Articulo articulo){
		populateConsumptionMap(articulo);
		Map<MateriaPrima, CommandMPCostsDetails> mcmpd = new HashMap<MateriaPrima, CommandMPCostsDetails>();
		List<MateriaPrima> mps;
		if (tipoProductivo.getId() == TipoLinea.INDUSTRIAL){
			mps = QueryUtil.getInstance().getMateriaPrimaByPapel();
		}else{
			mps = QueryUtil.getInstance().getMateriaPrimaByCartulina();
		}
		
		for (MateriaPrima mp : mps){
			CommandMPCostsDetails cmpd = valoresPorMateriaPrima(mp);
			mcmpd.put(mp, cmpd);
		}
		
		return mcmpd;
	}
	
	/*Los precios se expresan en dolares*/
	public CommandMPCostsDetails valoresPorMateriaPrima(MateriaPrima m){
		CommandMPCostsDetails cmpd = new CommandMPCostsDetails(m);
		Double total = 0.0;
		List<TipoMateriaPrima> tipos = QueryUtil.getInstance().getTipoMateriaPrimaExceptsMOByTipo(this.tipoProductivo);
		for (TipoMateriaPrima tipo : tipos){
			
			Double consumo = calculateConsumption(tipo);
			Double cUnit = 0.0;
			Double costoParcial = 0.0;
			
			if  (	
					m.getGramaje() != null
				&& 
					(tipo.getId() == TipoMateriaPrima.PAPEL || tipo.getId() == TipoMateriaPrima.CARTULINA)
				){
				cUnit = m.getCostoUnitario()*m.getGramaje();
			}else if( tipo.getId() == TipoMateriaPrima.MODULO ){
				cUnit = m.getCostoUnitario();
			}else if(tipo.getId() == TipoMateriaPrima.FONDO){
				cUnit = calculateCostNoPaper(tipo)*m.getGramaje();
			}else{
				cUnit = calculateCostNoPaper(tipo); 
			}
			costoParcial = (consumo * cUnit)/moneda.getCotizacion();
			cmpd.putCost(tipo, costoParcial);
			total += costoParcial; 
		}
		
		Double scrap = total * proporcionScrap;
		total += scrap;
		
		cmpd.setScrap(scrap);
		cmpd.setTotal(total);
		
		return cmpd;
	}
	
	private Double calculateCostNoPaper(TipoMateriaPrima tipo ){
		if(this.costosMateriasPrimasNoPapel == null){
			populateCostsNoPaperMap();
		}
		
		if (this.costosMateriasPrimasNoPapel.containsKey(tipo)){
			return this.costosMateriasPrimasNoPapel.get(tipo);
		}else{
			return null;
		}
	}

	private void populateCostsNoPaperMap(){
		this.costosMateriasPrimasNoPapel = new HashMap<TipoMateriaPrima, Double>();
		List<TipoMateriaPrima> tipos = QueryUtil.getInstance().getTipoMateriaPrimaExceptsMOByTipo(this.tipoProductivo);
		
		for (TipoMateriaPrima tipo : tipos){
			MateriaPrima mp = QueryUtil.getInstance().getMateriaPrimaByTipoMateria(tipo).get(0);
			mp.setCostoUnitario( (mp.getCostoUnitario() != null)? mp.getCostoUnitario() : 0.0 );
			this.costosMateriasPrimasNoPapel.put(tipo, mp.getCostoUnitario());
		}
	}
	
	
	private Double calculateConsumption(TipoMateriaPrima tipo ){
//		if(this.consumosMateriasPrimas == null){
//			
//		}
		if (this.consumosMateriasPrimas.containsKey(tipo)){
			return this.consumosMateriasPrimas.get(tipo);
		}else{
			return null;
		}
	}
	
	private void populateConsumptionMap(Articulo articulo){
		this.consumosMateriasPrimas = new HashMap<TipoMateriaPrima, Double>();
		List<TipoMateriaPrima> tipos = QueryUtil.getInstance().getTipoMateriaPrimaExceptsMOByTipo(tipoProductivo);
		
		for (TipoMateriaPrima tipo : tipos){
			MateriaPrimaArticulo consumo = QueryUtil.getInstance().getMateriaPrimaArticulo(articulo, tipo);
			if(consumo != null){
				this.consumosMateriasPrimas.put(tipo, consumo.getConsummo());				
			}else{
				this.consumosMateriasPrimas.put(tipo, 0.0);
			}
		}
	}

	public Map<TipoMateriaPrima, Double> getConsumosMateriasPrimas() {
		return consumosMateriasPrimas;
	}
	
	
}
